#pragma once
#include <fstream>
using namespace std;

//CRC-15-CAN: x15 + x14 + x10 + x8 + x7 + x4 + x3 + 1
const bool POLYNOMIAL[16] = {true,true,false,false,false,true,false,true,true,false,false,true,true,false,false,true};

const int SoF = 1;
const int ARB = 12;
const int CON = 6;
const int DAT = 64; //Max length of Data Field is 64.
const int CRC = 16;
const int CRC_BODY = 15;
const int ACK = 2;
const int EoF = 7;
const int DATCRC_INPUT = SoF+ARB+CON+DAT+15; //98
const int RMTCRC_INPUT = SoF+ARB+CON+15; //34
const int DATFRM_LEN = SoF+ARB+CON+DAT+CRC+ACK+EoF; //108
const int RMTFRM_LEN = SoF+ARB+CON+CRC+ACK+EoF; //44
const int MAX_ID = 1015;

enum FrameType
{
	General,
	Data,
	Remote,
	Error,
	Overload
};

class Frame
{
protected:
	bool* mBits;
	int mLength;
public:
	Frame();
	~Frame();
	bool getBit(int);
	int getLength();
	virtual bool isValid() = 0;
	virtual FrameType getFrameType();
};

/*
----DATA FRAME
START OF FRAME: 1 bit, d
ARBITRATION FIELD: 11 bit ID (first 7 bits must not be all r); 1 bit RTR, d
CONTROL FIELD: 2 bit reserved, d; 4 bit DATA LENGTH CODE
DATA FIELD: 0 to 8 bytes (0 to 64 bits)
CRC FIELD: 15 bits CRC, 1 bit DELIMITER, r
ACK FIELD: 1 bit SLOT, 1 DELIMITER, r
END OF FRAME: 7 bits, r

ONE DATA FRAME: d (11x)d (4x)dd [0~64x] (15x)r xr rrrrrrr
Total: 44~108 bits
*/
class DataFrame : public Frame
{
private:
	int mDATLength;
public:
	DataFrame(unsigned int,unsigned int); //specify ID and DATA LENGTH CODE
	~DataFrame();
	bool isValid();
	void print();
	FrameType getFrameType();
};

/*
----REMOTE FRAME
START OF FRAME: 1 bit, d
ARBITRATION FIELD: 11 bit ID (first 7 bits must not be all r); 1 bit RTR, r   
CONTROL FIELD: 2 bit reserved, d; 4 bit DATA LENGTH CODE
CRC FIELD: 15 bits CRC, 1 bit DELIMITER, r
ACK FIELD: 1 bit SLOT, 1 DELIMITER, r
END OF FRAME: 7 bits, r

ONE DATA FRAME: d (11x)d (4x)dd (15x)r xr rrrrrrr
Total: 44 bits
*/
class RemoteFrame : public Frame
{
private:
	int mDATLength;
public:
	RemoteFrame(unsigned int, unsigned int);
	~RemoteFrame();
	bool isValid();
	void print();
	FrameType getFrameType();
};

/*
----ERROR FRAME
superposition of ERROR FLAGS: 6 to12 bits, (6d for ACTIVE ERROR FLAG, initially 6r for PASSIVE ERROR FLAG)
ERROR DELIMITER: 8 bits, r
*/
class ErrorFrame : public Frame
{};

/*
----OVERLOAD FRAME
superposition of OVERLOAD FLAGS: 6 to 12 bits, d
OVERLOAD DELIMITER: 8 bits, r
*/
class OverloadFrame : public Frame
{};


/*
----INTERFRAME SPACING
INTERMISSION: 3 bits, r
SUSPEND TRANSMISSION: 
BUS IDLE: 
*/
class InterframeSpacing : public Frame
{};